﻿<cfsilent>
	<cfscript>
	
		jsonAdvice = getProperty("serviceFactory").getBean("jsonAdvice");
		mathAdvice = getProperty("serviceFactory").getBean("senateMathAdvice");
		
		sequenceClassroomTimeTable = getProperty("serviceFactory").getBean("sequenceClassroomTimeTable");
		sequenceStudentExamResit = getProperty("serviceFactory").getBean("sequenceStudentExamResit");
		
		response = structNew();
		structInsert(response, "success", false, true);
		structInsert(response, "reason", "没有适合的考试时间", true);
		
		progress = [];
		rooms = [];

		examId = event.getArg("EXID");
		
		/* 加载考试任务 */
		
		sql = "SELECT a.rstidx,
					   a.term_id,
					   a.wid,
					   a.cid,
					   a.examer_sum,
					   a.campus_id
				FROM t_resittask a 
				WHERE a.task_exrstid = :examId ";
				
		queryObj = new Query( datasource=application.dnsSlave ) ;
   		queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
		
		rs_examTask= queryObj.execute( sql=sql ).getResult();
		
		/* 设置考试可用的时间 */
		timeTable = arrayNew(2);
		
		for(weekDay=1; weekDay lte 7; weekDay++){
			for(lecture=1; lecture lte 5; lecture++){
				timeTable[weekDay][lecture] = 0;
			}
		}
		
		/* 选择补考加载时间设置数据 */
		
		/* 读取半期考试可用时间 */
		/* 第6位 是否用于补考 */
		
		sql = "SELECT a.wdidx, a.lecidx, a.props 
						FROM t_timetable a  
						WHERE 
							  SUBSTR(a.props, 6, 1)='1' 
							  AND 
							  a.lecidx IN ('1','2','3','4','5')";
				
		queryObj = new Query( datasource=application.dnsSlave) ;
		
		rs_timeSet= queryObj.execute( sql=sql ).getResult();
		
		for ( a=1; a LTE rs_timeSet.recordCount; a++ ) {
			timeTable[rs_timeSet["wdidx"][a]][rs_timeSet["lecidx"][a]] = 1;
		}
		
		
		/* 检查现有考试冲突 */
		
		courseId=rs_examTask.cid; 
		termId=rs_examTask.term_id; 
		examIdx=rs_examTask.rstidx;
		
		sql = "SELECT a.task_id 
				FROM t_resitplan a  
				WHERE a.cid = :courseId  
					  AND 
					  a.term_id = :termId 
					  AND 
					  a.rstidx = :examIdx ";
					  
		queryObj = new Query( datasource=application.dnsSlave ) ;
   		queryObj.addParam( name="courseId", value=courseId, cfsqltype="cf_sql_varchar" );
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
		queryObj.addParam( name="examIdx", value=examIdx, cfsqltype="cf_sql_char" );
		
		rs_taskIds= queryObj.execute( sql=sql ).getResult();
		
		examWeek = rs_examTask.wid;

		/* 学生不能同时安排两场考试 */
														
		sql = "SELECT 
				a.wdidx, a.cellidx 
				FROM t_resittask a
				WHERE 
					( a.task_exrstid > :examId 
					  OR 
					  a.task_exrstid < :examId 
					 ) 
					AND 
					a.wdidx > '0' 
					AND 
					a.wid = :examWeek 
					AND 
					a.term_id = :termId 
					AND 
					EXISTS (
						SELECT 1
						FROM t_resitplan b
						WHERE 
							a.cid = b.cid 
							AND 
							a.term_id = b.term_id 
							AND 
							a.rstidx = b.rstidx 
							AND 
							EXISTS (
								  SELECT 1
								  FROM t_temp_mark_resit e 
								  WHERE 
									e.task_id= b.task_id 
									AND 
									EXISTS (
									  SELECT 1
										FROM t_temp_mark_resit d
										WHERE 
											d.stu_id = e.stu_id
											AND 
											d.task_id IN ( :taskIds )
									
									)
							)
						)";
						
		queryObj = new Query( datasource=application.dnsSlave ) ;
   		queryObj.addParam( name="taskIds", value= arrayToList(rs_taskIds["task_id"],"|"), cfsqltype="cf_sql_varchar",list = true,separator="|"  );
		queryObj.addParam( name="examWeek", value=examWeek, cfsqltype="cf_sql_char" );
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
		queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_varchar" );
		
		rs_conflictExam= queryObj.execute( sql=sql ).getResult();
		
		for (  b=1; b LTE rs_conflictExam.recordCount; b++  ) {
			timeTable[rs_conflictExam["wdidx"][b]][rs_conflictExam["cellidx"][b]] = -3;
		}
		
		
		/* 检查教室是否足够 */
		studentCount = rs_examTask.examer_sum;
		campusId = rs_examTask.campus_id;
		termId = rs_examTask.term_id;
		examWeek = rs_examTask.wid;
		
		/* 进行开学前学期修正 */
		if ( examWeek eq -1 ) { examWeek = 25; }
		
		for(weekDay=1; weekDay lte 7; weekDay++){
			for(lecture=1; lecture lte 5; lecture++){
				
				if ( timeTable[weekDay][lecture] eq 1 ) {
					
					cells = 2;
					/* 如果为 第二讲 或 第五讲 则使用最长学时数 */
					if (lecture eq 2 or lecture eq 5) { cells = 3; }
					
					cellStart = mathAdvice.convertLectureIdxToCellStart(lecture);
					cellEnd = cellStart + cells -1;
					
					sql = "SELECT 
							case when sum(a.sits_exam) is null then 0 else sum(a.sits_exam) end sits_exam
							FROM t_classroom a 
							WHERE 
								SUBSTR(a.cr_usage, 3, 1) = '1' 
								AND 
								(a.campus_id= :campusId )
								AND 
								NOT EXISTS (
									SELECT 1
									FROM t_clsroom_timetable b
									WHERE 
										a.cr_id = b.cr_id
										AND 
										b.term_id = :termId 
										AND 
										b.wdidx = :weekDay 
										AND
										NOT ( b.cellidx + b.cellrelay -1 < :cellStart 
												OR 
												b.cellidx > :cellEnd 
											  ) 
										AND 
										SUBSTR(b.widx, #int(examWeek)#, 1) = '1' 
								)";
								
					queryObj = new Query( datasource=application.dnsSlave ) ;
					queryObj.addParam( name="weekDay", value=weekDay, cfsqltype="cf_sql_char" );
					queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer" );
					queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
					queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer" );
					queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char" );
					
					rs_clsroomCheck= queryObj.execute( sql=sql ).getResult();

					
					/* 如果可用考场座位数 没有超过应考人数10 */
					
					if ( rs_clsroomCheck.recordCount ) {
						
						if ( rs_clsroomCheck["sits_exam"][1] lt studentCount + 10 ) {
							timeTable[weekDay][lecture] = -4;
						}
					}
					else {
						timeTable[weekDay][lecture] = -4;
					}
					
				}
			
			}
		}
		
		/* 生成最终返回 可以排考的时间数据 */
		
		availableTimeSet = [];
		
		notDone = true;
		
		for(weekDay=1; weekDay lte 7; weekDay++){
			for(lecture=1; lecture lte 5; lecture++){
				
				if ( timeTable[weekDay][lecture] eq 1 and notDone) {
					
					
					transaction {
						
						/* 加载考试任务 */
					
						sql = "SELECT a.task_prog 
								FROM t_resittask a 
								WHERE a.task_exrstid = :examId ";
														
						queryObj = new Query( datasource=application.dnsMaster ) ;
						queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
						
						rs_resitTasks= queryObj.execute( sql=sql ).getResult();
						
						/* 设置时间 */
						if ( rs_resitTasks.task_prog eq "0" ) {
							
							arrayAppend( progress, "正在将考试安排在周" & weekDay & "第" & lecture & "场" );
							
							/* 考试场次 */
							examCell =  lecture;
							
							/* 保存考试时间安排 */
							ExamWeekDay = weekDay ;
							ExamCell = examCell ;
			
							/* 更新排考进度 */
							TaskProgress = "1" ;
							
							sql = "UPDATE t_resittask a 
									SET a.wdidx = :ExamWeekDay ,
										a.cellidx = :ExamCell ,
										a.task_prog = :TaskProgress 
									WHERE a.task_exrstid = :examId ";
									
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="ExamWeekDay", value=ExamWeekDay, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="ExamCell", value=ExamCell, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="TaskProgress", value=TaskProgress, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
							queryObj.execute( sql=sql );
							
							/* 数据密闭 */
							
							/* 如果已经保存了学生考试安排 则全部删除 */
							
							sql = "DELETE 
									FROM t_student_resit a 
									WHERE a.task_exrstid = :examId ";
									
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
							queryObj.execute( sql=sql );
							
							/* 如果已经保存了场地占用 则全部删除 */
							
							sql = "DELETE 
									FROM t_clsroom_timetable a 
									WHERE a.crtime_id IN (
										  SELECT b.crtime_id
										  FROM t_clsroom_forresit b 
										  WHERE b.task_exrstid = :examId 
									)";
							
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
							queryObj.execute( sql=sql );
							
							sql = "SELECT a.task_prog ,
									   a.task_exrstid,
									   a.term_id,
									   a.rstidx,
									   a.cid,
									   b.course_name,
									   a.wid,
									   a.wdidx,
									   a.cellidx,
									   a.campus_id
								FROM t_resittask a 
									 INNER JOIN t_course b ON b.cid = a.cid 
								WHERE a.task_exrstid = :examId ";
														
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
							
							rs_resitTask= queryObj.execute( sql=sql ).getResult();	
						}
						
						/* 设置地点 */
						if ( rs_resitTask.task_prog eq "1" ) {
							
							usage = "3";
						
							term = rs_resitTask.term_id;
							termId = rs_resitTask.term_id;
							examIdx = rs_resitTask.rstidx;
							courseId = rs_resitTask.cid;
							courseName = rs_resitTask.course_name;
							
							/* 获取考试的教学班列表 */
						
							sql = "SELECT 
									a.task_id 
									FROM t_resitplan a  
									WHERE 
										a.cid= :courseId 
										AND 
										a.term_id= :termId 
										AND 
										a.rstidx = :examIdx ";
													
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="courseId", value=courseId, cfsqltype="cf_sql_varchar" );
							queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="examIdx", value=examIdx, cfsqltype="cf_sql_char" );
							
							rs_taskId= queryObj.execute( sql=sql ).getResult();
							
							/* 需参加补考的学生 */
														
							sql = "SELECT 
									a.stu_id, a.scc_id
									FROM t_temp_mark_resit a  
									WHERE 
										a.task_id IN (:taskIds ) 
									ORDER BY a.task_id";
									
							queryObj = new Query( datasource=application.dnsMaster ) ;
							queryObj.addParam( name="taskIds", value=arrayToList(rs_taskId["task_id"],"|"), cfsqltype="cf_sql_varchar",list = true, separator="|" );
							
							rs_student= queryObj.execute( sql=sql ).getResult();
							
							studentCount = rs_student.recordCount;
							
							arrayAppend( progress, "课程补考人数为 " & studentCount & "人" );
							
							/* 刷新考试人数 */
							
							examWeek = int(rs_resitTask.wid);
							examWeekDay = rs_resitTask.wdidx;
							examCell = rs_resitTask.cellidx;
							campusId = rs_resitTask.campus_id;	
					
							examWeekIdx = mathAdvice.convertExamWeekIdx(examWeek);
							
							/* 进行开学前学期修正 */
							if ( examWeek eq -1 ) { examWeek = 25; }
					
							cells = 2;
							/* 如果为 第二讲 或 第五讲 则使用最长学时数 */
							if (examCell eq 2 or examCell eq 5) { cells = 3; }
							
							cellStart = mathAdvice.convertLectureIdxToCellStart(examCell);
							cellEnd = cellStart + cells -1;
							
							/* 首先尝试一个教室可以放下 */
							/* 大小适合 且尺寸最小 */
						
							weekDay=examWeekDay; 
					
							sql = "SELECT 
									a.cr_id 
									FROM t_classroom a 
									WHERE 
										SUBSTR(a.cr_usage, 3, 1) = '1' 
										AND 
										a.campus_id= :campusId 
										AND 
										a.sits_exam > :studentCount 
										AND 
										NOT EXISTS (
											SELECT 1
											FROM t_clsroom_timetable b
											WHERE 
												a.cr_id = b.cr_id
												AND 
												b.term_id = :termId 
												AND 
												b.wdidx = :weekDay 
												AND
												NOT ( b.cellidx + b.cellrelay -1 < :cellStart 
														OR 
														b.cellidx > :cellEnd 
													  ) 
												AND 
												SUBSTR(b.widx, #int(examWeek)#, 1) = '1' 
										) 
									ORDER BY a.sits_exam ";
								
							queryObj = new Query( datasource=application.dnsMaster,maxRows = 1 ) ;
							queryObj.addParam( name="studentCount", value=studentCount+2, cfsqltype="cf_sql_integer" );
							queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="weekDay", value=weekDay, cfsqltype="cf_sql_char" );
							queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer" );
							queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer" );
							queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char" );
							
							rs_clsroom= queryObj.execute( sql=sql ).getResult();

							if ( rs_clsroom.recordCount ) {
								
									arrayAppend( progress, "可以安排在一个考场进行" );
							
									/* 一个考场即足够 则标注该考场已使用 */
									clsroomId = rs_clsroom["cr_id"][1];
									
									sql = "SELECT a.sits_exam,
												   a.cr_id,
												   a.classroom
											FROM t_classroom a 
											WHERE a.cr_id = :clsroomId ";
											
									queryObj = new Query( datasource=application.dnsMaster ) ;
									queryObj.addParam( name="clsroomId", value=clsroomId, cfsqltype="cf_sql_char");
									
									rs_classRoom= queryObj.execute( sql=sql ).getResult();
									
									sequenceClassroomTimeTable.setTermID(termId);
									sequenceClassroomTimeTable.setClassroomID(clsroomId);
									
									useIdx = sequenceClassroomTimeTable.getIDX();
									
									sequenceClassroomTimeTable.setIndex(useIdx);
									
									useId = sequenceClassroomTimeTable.getID();
									
									ClassRoomTimeID = useId;
									UseIndex = useIdx;
									TaskResitExamID = examId; 
									ExamCourses = courseName;
									CourseCount = 1; 
									SitUsed = studentCount;
									SitLeft = rs_classRoom.sits_exam-studentCount;
									WeekIndex = mathAdvice.convertExamWeekIdx(examWeek);
									WeekDay = examWeekDay;
									CellStart = cellStart;
									CellLength = cells;
									Term = term;
									ClassRoom = clsroomId;
									Usage = usage;
									
									sql = "INSERT INTO t_clsroom_timetable (
												   crtime_id,
												   uidx,
												   widx,
												   wdidx,
												   cellidx,
												   cellrelay,
												   term_id,
												   cr_id,
												   ut_id
											) VALUES (
													:ClassRoomTimeID ,
													:UseIndex ,
													:WeekIndex ,																							                                                    :WeekDay ,																														                                                    :CellStart ,																														                                                    :CellLength ,																															                                                    :Term ,																																                                                    :ClassRoom ,																												                                                    :Usage 
											)";
											
									queryObj = new Query( datasource=application.dnsMaster) ;
									queryObj.addParam( name="ClassRoomTimeID", value=ClassRoomTimeID, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="UseIndex", value=UseIndex, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="WeekIndex", value=WeekIndex, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="WeekDay", value=WeekDay, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="CellStart", value=CellStart, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="CellLength", value=CellLength, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="Term", value=Term, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="ClassRoom", value=ClassRoom, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="Usage", value=Usage, cfsqltype="cf_sql_char" );
									queryObj.execute( sql=sql );
									
									sql = "INSERT INTO t_clsroom_forresit (
												   crtime_id,
												   task_exrstid,
												   exam_courses,
												   course_count,
												   sits_used,
												   sits_left
											) VALUES (
													:ClassRoomTimeID ,
													:TaskResitExamID , 																									        											:ExamCourses ,																												                                    				:CourseCount ,																																                                    				:SitUsed ,																															                                   		 			:SitLeft 		
											)";
											
									queryObj = new Query( datasource=application.dnsMaster) ;
									queryObj.addParam( name="ClassRoomTimeID", value=ClassRoomTimeID, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="TaskResitExamID", value=TaskResitExamID, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="ExamCourses", value=ExamCourses, cfsqltype="cf_sql_varchar" );
									queryObj.addParam( name="CourseCount", value=CourseCount, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="SitUsed", value=SitUsed, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="SitLeft", value=SitLeft, cfsqltype="cf_sql_integer" );
									queryObj.execute( sql=sql );

									/* 依次编排学生座位及考场 */
									sitidx = 0;
									
									for (c=1; c LTE rs_student.recordCount; c++) {
					
										sitidx++;
					
										student = rs_student["stu_id"][c];
					
										sequenceStudentExamResit.setTaskResitExamID(examId);
										sequenceStudentExamResit.setStudentID(student);
										stuExamId = sequenceStudentExamResit.getID();
										
										ExamerID = stuExamId;
										SitIndex = sitidx;
										ChooseID = rs_student["scc_id"][c]; 
										Student = student;
										ExamResitTask = examId;
										Classroom = clsroomId;
										
										sql = "INSERT INTO t_student_resit(
															scrsex_id, 
															sitidx, 
															scc_id, 
															stu_id, 
															task_exrstid, 
															cr_id 
														)VALUES(
															:ExamerID ,
															:SitIndex ,
															:ChooseID ,
															:Student ,
															:ExamResitTask ,
															:Classroom 
														)";
										
										queryObj = new query( datasource=application.dnsMaster );
										queryObj.addParam( name="ExamerID", value=stuExamId, cfsqltype="cf_sql_varchar" ); 
										queryObj.addParam( name="SitIndex", value=SitIndex, cfsqltype="cf_sql_integer" );
										queryObj.addParam( name="ChooseID", value=ChooseID, cfsqltype="cf_sql_varchar" );
										queryObj.addParam( name="Student", value=Student, cfsqltype="cf_sql_varchar" );
										queryObj.addParam( name="ExamResitTask", value=ExamResitTask, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="Classroom", value=Classroom, cfsqltype="cf_sql_char" );
										queryObj.execute( sql=sql );
					
									}
									
									/* 更新考试状态为已安排场地 */
									
									sql = "UPDATE t_resittask 
											SET examer_sum = :examSize, 
												task_prog = :taskProg 
											WHERE task_exrstid = :taskExamId ";
					 
									queryObj = new query( datasource=application.dnsMaster ); 
									queryObj.addParam( name="examSize", value=studentCount, cfsqltype="cf_sql_integer" ); 
									queryObj.addParam( name="taskProg", value="2", cfsqltype="cf_sql_char" ); 
									queryObj.addParam( name="taskExamId", value=examId, cfsqltype="cf_sql_char" ); 
									queryObj.execute( sql=sql );
							
									arrayAppend( rooms, [rs_classRoom.classroom, rs_classRoom.sits_exam, sitidx, 1, sitidx ] );
							
									structInsert(response, "success", true, true);
									
									/* 标注循环结束 */
									notDone = false;
							}
							else {
								
								/* 考试人数过多 一个考场无法安排 */
								
								arrayAppend( progress, "考试人数过多,单一考场无法安排; 尝试集中到楼层" );
								
								/* 首先尝试能否集中到某一个楼的某一个楼层 */
								/* 满足最大考试人数 最少的考场 */
							
														
								sql = "SELECT 
											a.b_id, 
											a.cr_floor, 
											SUM(a.sits_exam) sumExam, 
											COUNT(*) countCr 
										FROM 
											t_classroom a 
										WHERE 
											SUBSTR(a.cr_usage, 3, 1) = '1' 
											AND 
											a.campus_id = :campusId 
											AND 
											NOT EXISTS(
												SELECT 1 FROM t_clsroom_timetable b 
												WHERE 
												  b.cr_id = a.cr_id 
												  AND 
												  b.term_id = :termId 
												  AND 
												  b.wdidx = :weekDay 
												  AND 
												  NOT (b.cellidx + b.cellrelay - 1 < :cellStart OR b.cellidx > :cellEnd ) 
												  AND 
												  SUBSTR(b.widx, #int(examWeek)#, 1) = '1' )
										GROUP BY 
											a.b_id, a.cr_floor 
										HAVING 
											SUM(a.sits_exam) > :studentCount  
										ORDER BY 
											countCr ";
								
								queryObj = new query( datasource=application.dnsMaster, maxRows=1 ); 
								queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
								queryObj.addParam( name="weekDay", value=examWeekDay, cfsqltype="cf_sql_char" );
								queryObj.addParam( name="studentCount", value=studentCount+2, cfsqltype="cf_sql_integer" );
								queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer" );
								queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer" );
								queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char" );
								rs_floor = queryObj.execute( sql=sql ).getResult();

								if ( rs_floor.recordCount ) {
									
									/* 可以在一个楼层安排下来 */
									
									buildingId=rs_floor["b_id"][1];
									floorId=rs_floor["cr_floor"][1];
								
									sql = "SELECT 
												a.cr_id, 
												a.classroom, 
												a.sits_exam 
											FROM 
												t_classroom a 
											WHERE 
												SUBSTR(a.cr_usage, 3, 1) = '1' 
												AND 
												a.cr_floor = :floorId 
												AND 
												a.b_id = :buildingId 
												AND 
												a.campus_id = :campusId 
												AND 												
												NOT EXISTS(
													SELECT 1 FROM t_clsroom_timetable b 
													WHERE 
													  b.cr_id = a.cr_id 
													  AND 
													  b.term_id = :termId 
													  AND 
													  b.wdidx = :weekDay 
													  AND 
													  NOT (b.cellidx + b.cellrelay - 1 < :cellStart OR b.cellidx > :cellEnd) 
													  AND 
													  SUBSTR(b.widx, #int(examWeek)#, 1) = '1' ) 
											ORDER BY 
												a.classroom ";
									
									queryObj = new query( datasource=application.dnsMaster ); 
									queryObj.addParam( name="floorId", value=floorId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="buildingId", value=buildingId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="weekDay", value=examWeekDay, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer" );
									rs_clsrooms = queryObj.execute( sql=sql ).getResult();
								}
								else {
							
									arrayAppend( progress, "无法集中到某个楼层; 将考试场地集中分布到可用教学楼的各楼层" );
									
									/* 无法安排在一个楼层 则调用更多的教室 */
									/* 按照教学楼和楼层进行排序 */
								
									sql = "SELECT 
												a.cr_id, 
												a.classroom, 
												a.sits_exam 
											FROM 
												t_classroom a 
											WHERE 
												SUBSTR(a.cr_usage, 3, 1) = '1' 
												AND 
												a.campus_id = :campusId 
												AND 												
												NOT EXISTS(
													SELECT 1 FROM t_clsroom_timetable b 
													WHERE 
													  b.cr_id = a.cr_id 
													  AND 
													  b.term_id = :termId 
													  AND 
													  b.wdidx = :weekDay 
													  AND 
													  NOT (b.cellidx + b.cellrelay - 1 < :cellStart OR b.cellidx > :cellEnd) 
													  AND 
													  SUBSTR(b.widx, #int(examWeek)#, 1) = '1' ) 
											ORDER BY 
												a.b_id, a.cr_floor, a.classroom ";
									
									queryObj = new query( datasource=application.dnsMaster ); 
									queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="weekDay", value=examWeekDay, cfsqltype="cf_sql_char" );
									queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer" );
									queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer" );
									rs_clsrooms = queryObj.execute( sql=sql ).getResult();	
								}
								
								sitsCount = 0;
						
								for (  d=1; d LTE rs_clsrooms.recordCount; d++) {
									sitsCount = sitsCount + rs_clsrooms["sits_exam"][d];
								}
								
								arrayAppend( progress, "目前可用教室" & rs_clsrooms.recordCount & "个, 考场最高容量" & sitsCount & "座" );
								
								if ( sitsCount gte studentCount ) {

									/* 教室足够 */
									/* 开始可用考场和人数 */
							
									clsroomToArrange = [];
									sitsUsed = 0;
									
									for ( e=1; e LTE rs_clsrooms.recordCount; e++) {
								
										sitsUsed = sitsUsed + rs_clsrooms["sits_exam"][e];
								
										arrayAppend(clsroomToArrange, [  rs_clsrooms["cr_id"][e], rs_clsrooms["classroom"][e], rs_clsrooms["sits_exam"][e], 0 ] );
								
										if ( sitsUsed gte studentCount ) {
											break;
										}
									}
									
									roomCount = arrayLen(clsroomToArrange);
							
									/* 平均分配学生座次 */
									studentAvgPerRoom = int( studentCount / roomCount );
									studentLeft = studentCount;
									
									/* 先按照平均数分配人数 */
									for ( i=1; i lte roomCount; i++ ) {
								
										if ( clsroomToArrange[i][3] gte studentAvgPerRoom ) {
											clsroomToArrange[i][4] = studentAvgPerRoom;
											studentLeft = studentLeft - studentAvgPerRoom;
										}
										else {
											clsroomToArrange[i][4] = clsroomToArrange[i][3];
											studentLeft = studentLeft - clsroomToArrange[i][3];
										}
								
									}
									
									/* 再平均分配剩余人数 */
									while ( studentLeft gt 0 ) {

										for ( i=1; i lte roomCount; i++ ) {
									
											if ( studentLeft eq 0) {
												break;
											}
									
											if ( clsroomToArrange[i][4] lt clsroomToArrange[i][3] ) {
												clsroomToArrange[i][4] ++;
												studentLeft --;
											}
									
										}
								
									}
									
									arrayAppend( progress, "平均分布考场学生到" & roomCount & "个考场" );
									
									studentStart = 0;
									studentEnd = 0;
									
									for ( clsroomTarget in clsroomToArrange ) {
								
										/* 标注该考场已用于考试 */
										classRoom = clsroomTarget[1];
										
										sql = "SELECT a.sits_exam,
													   a.cr_id,
													   a.classroom
												FROM t_classroom a 
												WHERE a.cr_id = :clsroomId "; 
						
										queryObj = new query( datasource=application.dnsMaster );
										queryObj.addParam( name="clsroomId", value=clsroomTarget[1], cfsqltype="cf_sql_char" );
										rs_classRoom = queryObj.execute( sql=sql ).getResult();
										
										sequenceClassroomTimeTable.setTermID(termId);
										sequenceClassroomTimeTable.setClassroomID(rs_classRoom.cr_id);
									
										useIdx = sequenceClassroomTimeTable.getIDX();
									
										sequenceClassroomTimeTable.setIndex(useIdx);
									
										useId = sequenceClassroomTimeTable.getID();
									
										ClassRoomTimeID = useId;
										UseIndex = useIdx;
										TaskResitExamID=examId; 
										ExamCourses=courseName;
										CourseCount=1; 
										SitUsed=clsroomTarget[4];
										SitLeft=rs_classRoom.sits_exam-clsroomTarget[4];
										WeekIndex=mathAdvice.convertExamWeekIdx(examWeek);
										WeekDay=examWeekDay;
										CellStart=cellStart;
										CellLength=cells;
										Term=term;
										ClassRoom=classRoom;
										Usage=usage;
										
										sql = "INSERT INTO t_clsroom_timetable (
													   crtime_id,
													   uidx,
													   widx,
													   wdidx,
													   cellidx,
													   cellrelay,
													   term_id,
													   cr_id,
													   ut_id
												) VALUES (
														:ClassRoomTimeID ,
														:UseIndex ,
														:WeekIndex ,																							                                                    	:WeekDay ,																														                                                    	:CellStart ,																														                                                    	:CellLength ,																															                                                    	:Term ,																																                                                    	:ClassRoom ,																												                                                    	:Usage 
												)";
												
										queryObj = new Query( datasource=application.dnsMaster) ;
										queryObj.addParam( name="ClassRoomTimeID", value=ClassRoomTimeID, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="UseIndex", value=UseIndex, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="WeekIndex", value=WeekIndex, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="WeekDay", value=WeekDay, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="CellStart", value=CellStart, cfsqltype="cf_sql_integer" );
										queryObj.addParam( name="CellLength", value=CellLength, cfsqltype="cf_sql_integer" );
										queryObj.addParam( name="Term", value=Term, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="ClassRoom", value=ClassRoom, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="Usage", value=Usage, cfsqltype="cf_sql_char" );
										queryObj.execute( sql=sql );
										
										sql = "INSERT INTO t_clsroom_forresit (
													   crtime_id,
													   task_exrstid,
													   exam_courses,
													   course_count,
													   sits_used,
													   sits_left
												) VALUES (
														:ClassRoomTimeID ,
														:TaskResitExamID , 																									        												:ExamCourses ,																												                                    					:CourseCount ,																																                                    					:SitUsed ,																															                                   		 				:SitLeft 		
												)";
												
										queryObj = new Query( datasource=application.dnsMaster) ;
										queryObj.addParam( name="ClassRoomTimeID", value=ClassRoomTimeID, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="TaskResitExamID", value=TaskResitExamID, cfsqltype="cf_sql_char" );
										queryObj.addParam( name="ExamCourses", value=ExamCourses, cfsqltype="cf_sql_varchar" );
										queryObj.addParam( name="CourseCount", value=CourseCount, cfsqltype="cf_sql_integer" );
										queryObj.addParam( name="SitUsed", value=SitUsed, cfsqltype="cf_sql_integer" );
										queryObj.addParam( name="SitLeft", value=SitLeft, cfsqltype="cf_sql_integer" );
										queryObj.execute( sql=sql );
										
										/* 依次编排学生座位及考场 */
										sitidx = 0;
										studentStart = studentEnd + 1;
										studentEnd = studentEnd + clsroomTarget[4];
										
										
										
										for ( i=studentStart; i lte studentEnd; i++ ) {
									
											sitidx++;
					
											student = rs_student["stu_id"][i];

											
											sequenceStudentExamResit.setTaskResitExamID(examId);
											sequenceStudentExamResit.setStudentID(student);
											stuExamId = sequenceStudentExamResit.getID();
											
											ExamerID = stuExamId;
											SitIndex = sitidx;
											ChooseID = rs_student["scc_id"][i]; 
											Student = student;
											ExamResitTask = examId;
											Classroom = classRoom;
											
											sql = "INSERT INTO t_student_resit(
																scrsex_id, 
																sitidx, 
																scc_id, 
																stu_id, 
																task_exrstid, 
																cr_id 
															)VALUES(
																:ExamerID ,
																:SitIndex ,
																:ChooseID ,
																:Student ,
																:examId ,
																:Classroom 
															)";
											
											queryObj = new query( datasource=application.dnsMaster );
											queryObj.addParam( name="ExamerID", value=ExamerID, cfsqltype="cf_sql_varchar" ); 
											queryObj.addParam( name="SitIndex", value=SitIndex, cfsqltype="cf_sql_integer" );
											queryObj.addParam( name="ChooseID", value=ChooseID, cfsqltype="cf_sql_varchar" );
											queryObj.addParam( name="Student", value=Student, cfsqltype="cf_sql_varchar" );
											queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
											queryObj.addParam( name="Classroom", value=Classroom, cfsqltype="cf_sql_char" );
											queryObj.execute( sql=sql );
									
										}
										
										arrayAppend( rooms, [rs_classRoom.classroom, rs_classRoom.sits_exam, clsroomTarget[4], studentStart, studentEnd ] );

								
									}
							
									/* 更新考试状态为已安排场地 */
									
									sql = "UPDATE t_resittask 
											SET examer_sum = :examSize, 
												task_prog = :taskProg 
											WHERE task_exrstid = :taskExamId ";
					 
									queryObj = new query( datasource=application.dnsMaster ); 
									queryObj.addParam( name="examSize", value=studentCount, cfsqltype="cf_sql_integer" ); 
									queryObj.addParam( name="taskProg", value="2", cfsqltype="cf_sql_char" ); 
									queryObj.addParam( name="taskExamId", value=examId, cfsqltype="cf_sql_char" ); 
									queryObj.execute( sql=sql );
							
									arrayAppend( progress, "编排学生座次完成" );
							
									structInsert(response, "success", true, true);
									
									/* 标注循环结束 */
									notDone = false;
							
								}
								else {
									/* 考场不足 */
									structInsert(response, "reason", "当前考试时间没有足够的考场", true);
									
									arrayAppend( progress, "当前考试时间没有足够的考场" );
								}
				
							}
							
						}


					}
					
					
				}
				
			}
		}

		structInsert(response, "Progress", progress, true);
		structInsert(response, "ClassRoom", rooms, true);
		
	</cfscript>
</cfsilent><cfoutput>#jsonAdvice.encode(data:response, stringNumbers:true)#</cfoutput>